/**
 * @author Raghav Sood
 * @version 1
 * @date 26 January, 2013
 */
package com.coollang.smartbra.views;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;


/**
 * 作者：陈冬冬
 * <p>
 * 说明：圆形的seekbar
 * 普通模式，地图模式界面中的长按暂停用到
 * <p>
 * 时间：2015-10-19 下午4:09:09
 */
public class CircularSeekBarBcg extends View {


    /**
     * The listener to listen for changes
     */
    private OnSeekChangeListener mListener;

    /**
     * The color of the progress ring
     */
    private Paint circleColor;

    /** the color of the inside circle. Acts as background color */
//	private Paint innerColor;

    /** The progress circle ring background */
//	private Paint circleRing;

    /**
     * The angle of progress
     */
    private int angle = 0;

    /**
     * The start angle (12 O'clock
     */
    private int startAngle = 270;

    /**
     * The width of the progress ring
     */
    private int barWidth = 5;

    /**
     * The width of the view
     */
    private int width;

    /**
     * The height of the view
     */
    private int height;

    /**
     * The maximum progress amount
     */
    private int maxProgress = 100;

    /**
     * The current progress
     */
    private int progress;

    /**
     * The progress percent
     */
    private int progressPercent;

    /**
     * The radius of the inner circle
     */
    private float innerRadius;

    /**
     * The radius of the outer circle
     */
    private float outerRadius;

    /**
     * The circle's center X coordinate
     */
    private float cx;

    /**
     * The circle's center Y coordinate
     */
    private float cy;

    /**
     * The left bound for the circle RectF
     */
    private float left;

    /**
     * The right bound for the circle RectF
     */
    private float right;

    /**
     * The top bound for the circle RectF
     */
    private float top;

    /**
     * The bottom bound for the circle RectF
     */
    private float bottom;

    /**
     * The adjustment factor. This adds an adjustment of the specified size to
     * both sides of the progress bar, allowing touch events to be processed
     * more user friendly (yes, I know that's not a word)
     */
    private float adjustmentFactor = 100;

    /** The progress mark when the view isn't being progress modified */
//	private Bitmap progressMark;

    /** The progress mark when the view is being progress modified. */
//	private Bitmap progressMarkPressed;

    /**
     * The flag to see if the setProgress() method was called from our own
     * View's setAngle() method, or externally by a user.
     */
    private boolean CALLED_FROM_ANGLE = false;

    /**
     * The rectangle containing our circles and arcs.
     */
    private RectF rect = new RectF();

    {
        mListener = new OnSeekChangeListener() {

            @Override
            public void onProgressChange(CircularSeekBarBcg view, int newProgress) {

            }
        };

        circleColor = new Paint();
        circleColor.setColor(Color.parseColor("#ffbd4a"));
        circleColor.setAntiAlias(true);
        circleColor.setStrokeWidth(20);
        circleColor.setStyle(Paint.Style.STROKE);

    }

    /**
     * Instantiates a new circular seek bar.
     *
     * @param context  the context
     * @param attrs    the attrs
     * @param defStyle the def style
     */
    public CircularSeekBarBcg(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * Instantiates a new circular seek bar.
     *
     * @param context the context
     * @param attrs   the attrs
     */
    public CircularSeekBarBcg(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * Instantiates a new circular seek bar.
     *
     * @param context the context
     */
    public CircularSeekBarBcg(Context context) {
        super(context);
    }


    /*
     * (non-Javadoc)
     *
     * @see android.view.View#onMeasure(int, int)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        height = getMeasuredHeight();
        width = getMeasuredWidth();
//		width = getWidth(); // Get View Width
//		height = getHeight();// Get View Height

        int size = (this.width > height) ? height : this.width; // Choose the smaller
        // between width and
        // height to make a
        // square

        cx = this.width / 2; // Center X for circle
        cy = height / 2; // Center Y for circle
        outerRadius = size / 2; // Radius of the outer circle

        innerRadius = outerRadius - barWidth; // Radius of the inner circle

        left = cx - outerRadius; // Calculate left bound of our rect
        right = cx + outerRadius;// Calculate right bound of our rect
        top = cy - outerRadius;// Calculate top bound of our rect
        bottom = cy + outerRadius;// Calculate bottom bound of our rect

        //Log.e("circleSeekbar", this.width + "=====" + height);

        rect.set(left + 10, top + 10, right - 10, bottom - 10); // assign size to rect
    }

    private int[] colors = new int[]{Color.parseColor("#52ff8a"), Color.parseColor("#51fe7e"), Color.parseColor("#52ff87"), Color.parseColor("#59ffc1"),
            Color.parseColor("#5dffe7"), Color.parseColor("#5dffea"), Color.parseColor("#5cffe4")};

    /*
     * (non-Javadoc)
     *
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
//		Shader shader = new SweepGradient(cx, cy, colors, null);
//		circleColor.setShader(shader);
        canvas.drawArc(rect, startAngle, angle, false, circleColor);
        super.onDraw(canvas);
    }

    /**
     * Get the angle.
     *
     * @return the angle
     */
    public int getAngle() {
        return angle;
    }

    /**
     * Set the angle.
     *
     * @param angle the new angle
     */
    public void setAngle(int angle) {
        this.angle = angle;
        float donePercent = (((float) this.angle) / 360) * 100;
        float progress = (donePercent / 100) * getMaxProgress();
        setProgressPercent(Math.round(donePercent));
        CALLED_FROM_ANGLE = true;
        setProgress(Math.round(progress));
    }

    /**
     * Sets the seek bar change listener.
     *
     * @param listener the new seek bar change listener
     */
    public void setSeekBarChangeListener(OnSeekChangeListener listener) {
        mListener = listener;
    }

    /**
     * Gets the seek bar change listener.
     *
     * @return the seek bar change listener
     */
    public OnSeekChangeListener getSeekBarChangeListener() {
        return mListener;
    }

    /**
     * Gets the bar width.
     *
     * @return the bar width
     */
    public int getBarWidth() {
        return barWidth;
    }

    /**
     * Sets the bar width.
     *
     * @param barWidth the new bar width
     */
    public void setBarWidth(int barWidth) {
        this.barWidth = barWidth;
    }

    /**
     * The listener interface for receiving onSeekChange events. The class that
     * is interested in processing a onSeekChange event implements this
     * interface, and the object created with that class is registered with a
     * component using the component's
     * <code>setSeekBarChangeListener(OnSeekChangeListener)<code> method. When
     * the onSeekChange event occurs, that object's appropriate
     * method is invoked.
     *
     * @see OnSeekChangeEvent
     */
    public interface OnSeekChangeListener {

        /**
         * On progress change.
         *
         * @param view        the view
         * @param newProgress the new progress
         */
        public void onProgressChange(CircularSeekBarBcg view, int newProgress);
    }

    /**
     * Gets the max progress.
     *
     * @return the max progress
     */
    public int getMaxProgress() {
        return maxProgress;
    }

    /**
     * Sets the max progress.
     *
     * @param maxProgress the new max progress
     */
    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    /**
     * Gets the progress.
     *
     * @return the progress
     */
    public int getProgress() {
        return progress;
    }

    /**
     * Sets the progress.
     *
     * @param progress the new progress
     */
    public void setProgress(int progress) {
        if (this.progress != progress) {
            this.progress = progress;
            if (!CALLED_FROM_ANGLE) {
                int newPercent = (this.progress * 100) / this.maxProgress;
                int newAngle = (newPercent * 360) / 100;
                this.setAngle(newAngle);
                this.setProgressPercent(newPercent);
            }
            mListener.onProgressChange(this, this.getProgress());
            CALLED_FROM_ANGLE = false;
        }
    }

    /**
     * Gets the progress percent.
     *
     * @return the progress percent
     */
    public int getProgressPercent() {
        return progressPercent;
    }

    /**
     * Sets the progress percent.
     *
     * @param progressPercent the new progress percent
     */
    public void setProgressPercent(int progressPercent) {
        this.progressPercent = progressPercent;
    }

    /**
     * Sets the ring background color.
     *
     * @param color the new ring background color
     */
    public void setRingBackgroundColor(int color) {
//		circleRing.setColor(color);
    }

    /**
     * Sets the back ground color.
     *
     * @param color the new back ground color
     */
    public void setBackGroundColor(int color) {
//		innerColor.setColor(color);
    }

    /**
     * Sets the progress color.
     *
     * @param color the new progress color
     */
    public void setProgressColor(int color) {
        circleColor.setColor(color);
        invalidate();
    }

    /*
     * (non-Javadoc)
     *
     * @see android.view.View#onTouchEvent(android.view.MotionEvent)
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        boolean up = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                moved(x, y, up);
                break;
            case MotionEvent.ACTION_MOVE:
                moved(x, y, up);
                break;
            case MotionEvent.ACTION_UP:
                up = true;
                moved(x, y, up);
                break;
        }
        return true;
    }

    /**
     * Moved.
     *
     * @param x  the x
     * @param y  the y
     * @param up the up
     */
    private void moved(float x, float y, boolean up) {
        float distance = (float) Math.sqrt(Math.pow((x - cx), 2) + Math.pow((y - cy), 2));
        if (distance < outerRadius + adjustmentFactor && distance > innerRadius - adjustmentFactor && !up) {
            float degrees = (float) ((float) ((Math.toDegrees(Math.atan2(x - cx, cy - y)) + 360.0)) % 360.0);
            // and to make it count 0-360
            if (degrees < 0) {
                degrees += 2 * Math.PI;
            }

            setAngle(Math.round(degrees));
            invalidate();

        } else {
            invalidate();
        }

    }

    /**
     * Gets the adjustment factor.
     *
     * @return the adjustment factor
     */
    public float getAdjustmentFactor() {
        return adjustmentFactor;
    }

    /**
     * Sets the adjustment factor.
     *
     * @param adjustmentFactor the new adjustment factor
     */
    public void setAdjustmentFactor(float adjustmentFactor) {
        this.adjustmentFactor = adjustmentFactor;
    }

}
